package com.derbysoft.ota.application.service.impl;

import static com.derbysoft.ota.interfaces.protocol._2009a.TransactionActionType.BOOK;
import static com.derbysoft.ota.interfaces.protocol._2009a.TransactionActionType.INITIATE;

import com.derbysoft.modules.eip.translator.Translator;
import com.derbysoft.modules.validation.ValidateUtils;
import com.derbysoft.ota.application.service.HotelResService;
import com.derbysoft.ota.application.translator.rs.HotelResResponseTypeSource;
import com.derbysoft.ota.interfaces.protocol._2009a.*;
import com.derbysoft.remote.dswitch.core.GenericRQ;
import com.derbysoft.remote.dswitch.core.GenericRS;
import com.derbysoft.remote.dswitch.core.RequestHeader;
import com.derbysoft.remote.dswitch.generic.constants.UniqueIDType;
import com.derbysoft.remote.dswitch.generic.dto.UniqueIDDTO;
import com.derbysoft.remote.dswitch.hotel.dswitch.DSwitch4HotelBuyerWebServiceFactory;
import com.derbysoft.remote.dswitch.hotel.dto.HotelReservationRQ;
import com.derbysoft.remote.dswitch.hotel.dto.HotelReservationRS;
import com.google.inject.Inject;

public class HotelResServiceImpl extends AbstractService implements HotelResService {

	private Translator<HotelResRequestType, HotelReservationRQ> rqTranslator;
	private Translator<HotelResResponseTypeSource, HotelResResponseType> rsTranslator;

	@Inject
	public HotelResServiceImpl(
		DSwitch4HotelBuyerWebServiceFactory dswitch4HotelBuyerWebServiceFactory,
		Translator<POSType, RequestHeader> requestHeaderTranslator,
		Translator<HotelResRequestType, HotelReservationRQ> rqTranslator,
		Translator<HotelResResponseTypeSource, HotelResResponseType> rsTranslator) {
		super(dswitch4HotelBuyerWebServiceFactory, requestHeaderTranslator);
		this.rqTranslator = rqTranslator;
		this.rsTranslator = rsTranslator;
	}

	@Override
	public HotelResResponseType make(HotelResRequestType requestObject) {
		GenericRQ<HotelReservationRQ> genericRQ = switchRequest(requestObject);

		ValidateUtils.validate(genericRQ);
		GenericRS<HotelReservationRS> genericRS = dswitch().makeReservation(genericRQ);
		ValidateUtils.validate(genericRS);

		return otaResponse(requestObject, genericRS);
	}

	private GenericRQ<HotelReservationRQ> switchRequest(HotelResRequestType requestObject) {
		HotelReservationRQ switchRQ = rqTranslator.translate(requestObject);
		RequestHeader requestHeader = requestHeader(requestObject.getPOS(), requestObject.getUniqueID(), true);
		requestHeader.getProducts().add(new UniqueIDDTO(hotelCode(switchRQ), UniqueIDType.HOTEL));
		return new GenericRQ<HotelReservationRQ>(requestHeader, switchRQ);
	}

	private String hotelCode(HotelReservationRQ switchRQ) {
		return switchRQ.getHotelReservation().getHotelRef().getCode();
	}

	private HotelResResponseType otaResponse(HotelResRequestType requestObject, GenericRS<HotelReservationRS> genericRS) {
		HotelReservationType requestedReservation = requestObject.getHotelReservations().getHotelReservation().iterator().next();
		HotelResResponseType otaRS = new HotelResResponseType();
		if (!handleResponseHeaders(genericRS, requestObject, otaRS)) {
			otaRS.setResResponseType(resResponseType(requestObject));
			return rsTranslator.translate(new HotelResResponseTypeSource(requestedReservation, otaRS, genericRS.getPayload()));
		}
		otaRS.setResResponseType(TransactionStatusType.UNSUCCESSFUL);
		return otaRS;
	}

	private TransactionStatusType resResponseType(HotelResRequestType requestObject) {
		TransactionActionType resStatus = requestObject.getResStatus();
		if (INITIATE == resStatus) {
			return TransactionStatusType.IGNORED;
		}
		if (BOOK == resStatus) {
			return TransactionStatusType.COMMITTED;
		}
		throw new UnsupportedOperationException("Unsupported transaction action type [" + resStatus +"], we only support Initiate and Book transaction action type.");
	}


}
